#include <Arduino.h>
#include <rtthread.h>
#include <TFT_eSPI.h>        // Hardware-specific library
#include "displayer.h"

#define SCREEN_WIDTH    135
#define SCREEN_HEIGHT   240
#define TEXT_HEIGHT     100

static TFT_eSPI tft = TFT_eSPI(SCREEN_WIDTH, SCREEN_HEIGHT);

// #define IMG_W 50
// #define IMG_H 50
// static uint16_t data[IMG_W * IMG_H];

rt_err_t sdisp_init(void)
{
    tft.begin();               // Initialise the display
    tft.fillScreen(TFT_BLACK); // Black screen fill

    // for(int i = 0; i < IMG_W * IMG_H; i++)
    // {
    //     data[i] = i < IMG_W * IMG_H / 3 ? RGB888TO565(255, 0, 0)
    //         : (i < IMG_W * IMG_H * 2 / 3 ? RGB888TO565(0, 80, 0) : RGB888TO565(0, 0, 255));
    // }

    return RT_EOK;
}

rt_err_t sdisp_show(rt_uint16_t *rgb_buf, rt_uint32_t width, rt_uint32_t height)
{
    static rt_uint16_t *disp_buf = NULL;
    static int disp_buf_size = 0;

    // tft.pushImage(0, 0, IMG_W, IMG_H, data);
    int tw = tft.width();
    int th = tft.height() - TEXT_HEIGHT;

    if(width > tw || height > th)
    {
        /* unsupport */
        return -RT_ENOSYS;
    }

    int scale_w = tw / width;
    int scale_h = th / height;
    int scale = min(scale_w, scale_h);

    if(scale == 1)
    {
        tft.pushImage((tw - width) / 2, (th - height) / 2, width, height, rgb_buf);
    }
    else
    {
        int disp_w = width * scale;
        int disp_h = height * scale;
        int disp_size = disp_w * disp_h;
        if(disp_buf_size <  disp_size)
        {
            if(disp_buf)
            {
                delete disp_buf;
                disp_buf = NULL;
            }

            disp_buf = new uint16_t[disp_size];
            disp_buf_size = disp_size;
        }

        uint16_t *origin_ptr = rgb_buf;
        uint16_t *disp_ptr = disp_buf;

        for(int y = 0; y < height; y++)
        {
            for(int x = 0; x < width; x++)
            {
                uint16_t value = *origin_ptr;
                uint16_t *p = disp_ptr;

                for(int i = 0; i < scale; i++)
                {
                    for(int j = 0; j < scale; j++)
                    {
                        *p++ = value;
                    }

                    p += (disp_w - scale);
                }

                origin_ptr++;
                disp_ptr += scale;
            }

            disp_ptr += (scale - 1) * disp_w;
        }

        tft.pushImage((tw - disp_w) / 2, (th - disp_h) / 2, disp_w, disp_h, disp_buf);
    }

    return RT_EOK;
}

rt_err_t sdisp_print(const char *text, int line_num)
{
    int oy = tft.height() - TEXT_HEIGHT;
    int y;

    tft.setTextSize(2);
    y = oy + line_num * tft.fontHeight();

    tft.drawString(String(text), 10, y);

    return RT_EOK;
}


